package magnet.processor.instances.aspects.index;

import com.squareup.javapoet.AnnotationSpec;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.TypeSpec;
import magnet.internal.Generated;
import magnet.internal.Index;
import magnet.internal.InstanceFactory;
import magnet.processor.instances.FactoryType;
import magnet.processor.instances.FactoryTypeVisitor;
import magnet.processor.instances.generator.CodeGenerator;
import magnet.processor.instances.generator.CodeWriter;

import javax.lang.model.element.Modifier;

public class FactoryIndexCodeGenerator implements FactoryTypeVisitor, CodeGenerator {

    private TypeSpec factoryIndexTypeSpec;
    private ClassName factoryIndexClassName;

    @Override
    public void exitFactoryClass(FactoryType factory) {
        String factoryPackage = factory.getFactoryType().packageName();
        String factoryName = factory.getFactoryType().simpleName();
        String factoryIndexName = factoryPackage.replace('.', '_') + "_" + factoryName;

        factoryIndexClassName = ClassName.get("magnet.index", factoryIndexName);
        factoryIndexTypeSpec = TypeSpec
                .classBuilder(factoryIndexClassName)
                .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
                .addAnnotation(Generated.class)
                .addAnnotation(
                        generateFactoryIndexAnnotation(
                                factory.getFactoryType(),
                                factory.getInterfaceType().reflectionName(),
                                factory.getClassifier()
                        )
                )
                .build();
    }

    private AnnotationSpec generateFactoryIndexAnnotation(ClassName factoryClassName, String instanceType, String classifier) {
        return AnnotationSpec.builder(Index.class)
                .addMember("factoryType", "$T.class", InstanceFactory.class)
                .addMember("factoryClass", "$T.class", factoryClassName)
                .addMember("instanceType", "$S", instanceType)
                .addMember("classifier", "$S", classifier)
                .build();
    }

    @Override
    public CodeWriter generateFrom(FactoryType factoryType) throws IllegalAccessException {
        factoryType.accept(this);
        return new CodeWriter(factoryIndexClassName.packageName(), factoryIndexTypeSpec);
    }
}
